#include "database/user_dao.hpp"
#include "database/db_connection.hpp"
#include "common/debug.hpp"

#include <sstream>

bool UserDao::createUser(const User& user) {
    DBConnection* db = DBConnection::getInstance();

    std::stringstream ss;
    ss << "INSERT INTO tbl_user (username, password, salt) VALUES ('"
        << db->escapeString(user.username) << "', '"
        << db->escapeString(user.password) << "', '"
        << db->escapeString(user.salt) << "')";

    return db->execute(ss.str());
}


std::optional<User> UserDao::getUserByUsername(const std::string& username) {
    DBConnection* db = DBConnection::getInstance();

    std::stringstream ss;

    ss << "SELECT id, username, password, salt, created_at, tomb FROM tbl_user "
       << "WHERE username = '"
       << db->escapeString(username) << "' AND tomb = 0";

    LOG_DEBUG("Executing SQL: %s", ss.str().c_str());

    MYSQL_RES* result = db->query(ss.str());
    if (!result) {           
        LOG_DEBUG("db->query() failed and returned a nullptr.");
        return std::nullopt;
    }

    LOG_DEBUG("Query successful. Number of rows returned: %llu", mysql_num_rows(result));

    MYSQL_ROW row = mysql_fetch_row(result);

    if (!row) {
        LOG_DEBUG("User '%s' not found in database (mysql_fetch_row returned nullptr).", username.c_str());
        mysql_free_result(result);
        return std::nullopt;
    }    

    LOG_DEBUG("User found. ID: %s, Username: %s", row[0], row[1]);

    User user;
    user.id = std::stoi(row[0]);
    user.username = row[1] ? row[1] : "";
    user.password = row[2] ? row[2] : "";
    user.salt = row[3] ? row[3] : "";
    user.created_at = row[4] ? row[4] : "";
    user.tomb = std::stoi(row[5] ? row[5] : "0");

    mysql_free_result(result);
    return user;
}


bool UserDao::userExists(const std::string& username) {
    return getUserByUsername(username).has_value();
}
